package com.quanquan.parking.Service;

import DTO.PageDTO;
import com.quanquan.parking.dao.InNotifyRepository;
import com.quanquan.parking.dao.OutNotifyRepository;
import com.quanquan.parking.dao.PayNotifyRepository;
import com.quanquan.parking.dao.UserCarReository;
import com.quanquan.parking.dto.PayNotifyDTO;
import com.quanquan.parking.entity.InNotify;
import com.quanquan.parking.entity.OutNotify;
import com.quanquan.parking.entity.PayNotify;
import com.quanquan.parking.entity.UserCar;
import com.quanquan.parking.etcp.ParkProxy;
import com.quanquan.parking.etcp.response.*;
import com.quanquan.parking.request.InNotifyRequest;
import com.quanquan.parking.request.OutNotifyRequest;
import com.quanquan.parking.request.PayNotifyRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import utils.DateUtils;
import utils.StringUtil;
import utils.UUIDGenerator;

import javax.persistence.criteria.Predicate;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * @ClassName:ParkingService
 * @Description:TODO
 * @Author:xiongjunbao
 * @Date:2019/4/3 13:23
 * @Version 1.0
 */
@Service
public class ParkingService {

    public static final String OK = "ok";
    private final UserCarReository userCarReository;

    private final ParkProxy parkProxy;
    private final PayNotifyRepository payNotifyRepository;
    private final InNotifyRepository inNotifyRepository;
    private final OutNotifyRepository outNotifyRepository;

    @Autowired
    public ParkingService(UserCarReository userCarReository, ParkProxy parkProxy, PayNotifyRepository payNotifyRepository, InNotifyRepository inNotifyRepository, OutNotifyRepository outNotifyRepository) {
        this.userCarReository = userCarReository;
        this.parkProxy = parkProxy;
        this.payNotifyRepository = payNotifyRepository;
        this.inNotifyRepository = inNotifyRepository;
        this.outNotifyRepository = outNotifyRepository;
    }

    public String getToken(String mobile) {
        return parkProxy.getToken(mobile);
    }

    /**
     * 通过用户手机号查找绑定的车牌
     *
     * @return
     * @Version 1.0
     */
    public CarNumResponse findByMobile(String mobile) {
        Date date = new Date();
        CarNumResponse carNumResponse = parkProxy.carnum(mobile);
        if (carNumResponse==null){
            return null;
        }
        List<String> carList = carNumResponse.getCarList();
        for (String plateNum : carList){
            UserCar userCar = userCarReository.findByMobileAndCarNumberAndStatusRemove(mobile,plateNum);
            if (userCar!=null){
                if (userCar.getStatusRemove()==1){
                    userCar.setUpdateTime(DateUtils.dateToString(date,DateUtils.TIMESTAMP));
                    userCar.setStatusRemove(0);
                    userCar.setStatusShow(0);
                    userCarReository.saveAndFlush(userCar);
                }else {
                    userCar.setUpdateTime(DateUtils.dateToString(date,DateUtils.TIMESTAMP));
                    userCarReository.saveAndFlush(userCar);
                }
            }else {
                UserCar localUserCar = new UserCar();
                localUserCar.setId(UUIDGenerator.getUUID());
                localUserCar.setCreateTime(DateUtils.dateToString(date,DateUtils.TIMESTAMP));
                localUserCar.setUpdateTime(DateUtils.dateToString(date,DateUtils.TIMESTAMP));
                localUserCar.setCarNumber(plateNum);
                localUserCar.setStatusRemove(0);
                localUserCar.setStatusShow(0);
                userCarReository.saveAndFlush(localUserCar);
            }
        }
        return carNumResponse;
    }

    /**
     * 绑定车辆
     *
     * @return
     */
    public DataResponse bindCar(String carNumber, String mobile) {
        Date date = new Date();
        //打通dtcp，绑定车牌
        DataResponse response = parkProxy.bindCar(carNumber, mobile);
        if (response.getCode()==0) {
            UserCar userCar = userCarReository.findByMobileAndCarNumberAndStatusRemove(mobile, carNumber);
            if (userCar != null) {
                if (userCar.getStatusRemove() == 1) {
                    userCar.setUpdateTime(DateUtils.dateToString(date, DateUtils.TIMESTAMP));
                    userCar.setMobile(mobile);
                    userCar.setStatusRemove(0);
                    userCar.setStatusShow(0);
                    userCarReository.saveAndFlush(userCar);
                } else {
                    userCar.setUpdateTime(DateUtils.dateToString(date, DateUtils.TIMESTAMP));
                    userCar.setMobile(mobile);
                    userCarReository.saveAndFlush(userCar);
                }
            } else {
                UserCar localUserCar = new UserCar();
                localUserCar.setId(UUIDGenerator.getUUID());
                localUserCar.setCreateTime(DateUtils.dateToString(date, DateUtils.TIMESTAMP));
                localUserCar.setUpdateTime(DateUtils.dateToString(date, DateUtils.TIMESTAMP));
                localUserCar.setCarNumber(carNumber);
                localUserCar.setMobile(mobile);
                localUserCar.setStatusRemove(0);
                localUserCar.setStatusShow(0);
                userCarReository.saveAndFlush(localUserCar);
            }
            return response;
        }
        return response;
    }

    /**
     * 解绑车辆
     *
     * @return
     */
    public String untyingCar(String carNumber, String mobile) {
        String msg = parkProxy.untyingCar(carNumber, mobile);
        if (msg==null){
            return null;
        }
        if ("ok".equals(msg)) {
            Date date = new Date();
            UserCar userCar = userCarReository.findByMobileAndCarNumber(mobile, carNumber);
            userCar.setUpdateTime(DateUtils.dateToString(date, DateUtils.TIMESTAMP));
            userCar.setStatusRemove(1);
            userCar.setStatusShow(0);
            userCarReository.saveAndFlush(userCar);
            return "success";
        }
        return msg;
    }

    /**
     * 查询停车费
     *
     * @param plateNumber
     * @param mobile
     * @return
     */
    public DataResponse orderRunPay(String plateNumber, String mobile) {
        //查询本地是否存在本地关系，若没有，绑定车牌
        UserCar userCar = userCarReository.findByMobileAndCarNumber(mobile,plateNumber);
        if (userCar==null){
            DataResponse response = bindCar(plateNumber,mobile);
           if (response.getMessage().equals("ok")){
            bindCar(plateNumber,mobile);
           }else {
               return response;
           }
        }
        //查询停车费
        return parkProxy.orderRunPay(plateNumber, mobile);
    }

    /**
     * 主动支付
     * @param mobile
     * @param orderId
     * @return
     */
    public DataResponse orderPay(String mobile, String orderId){
        return parkProxy.orderPay(mobile, orderId);
    }

    /**
     * 停车历史
     *
     * @param mobile
     * @return
     */
    public List<OrderHistoryResponse> orderHistory(String mobile) {
        return parkProxy.orderHistory(mobile);
    }

    /**
     * 查询停车场状态
     *
     * @return
     */
    public ParkingResponse parkingStatus() {
        ParkingResponse parkingResponse = new ParkingResponse();
        parkingResponse.setTotalSpace("114");
        parkingResponse.setStatus("充足");
        parkingResponse.setTime("2017-09-04 22:37:14");
       // ParkingResponse parkingResponse = parkProxy.parkingStatus(parkingId);
        return parkingResponse;
    }

    /**
     * 车辆进出场模拟
     * @param plateNumber
     */
    public SimulationResponse simulation(String plateNumber){
        return parkProxy.simulation(plateNumber);
    }

    /**
     * 发放优免券
     * @param carNumber
     * @param couponFreeId
     */
    public String record(String carNumber,String couponFreeId) throws UnsupportedEncodingException {
        return parkProxy.record(carNumber,couponFreeId);
    }

    public boolean payNotify(PayNotifyRequest request){
        PayNotify payNotify = new PayNotify();
        payNotify.setId(UUIDGenerator.getUUID());
        payNotify.setOrderId(request.getOrderId());
        payNotify.setPlateNumber(request.getPlateNumber());
        payNotify.setCoupon(request.getCoupon());
        payNotify.setCouponCode(request.getCouponCode());
        payNotify.setDiscountAmount(request.getDiscountAmount());
        payNotify.setFee(request.getFee());
        payNotify.setPaidServiceFee(request.getPaidServiceFee());
        payNotify.setOnceServiceFeePaid(request.getOnceServiceFeePaid());
        payNotify.setTime(request.getTime());
        payNotifyRepository.saveAndFlush(payNotify);
        return true;
    }

    public boolean inNotify(InNotifyRequest request){
        InNotify inNotify = new InNotify();
        inNotify.setId(UUIDGenerator.getUUID());
        inNotify.setSynId(request.getSynId());
        inNotify.setPlateNumber(request.getPlateNumber());
        inNotify.setParkId(request.getParkId());
        inNotify.setParkName(request.getParkName());
        inNotify.setEntranceTime(request.getEntranceTime());
        inNotify.setUserType(request.getUserType());
        inNotify.setFixParkingId(request.getFixParkingId());
        inNotify.setPushTime(request.getPushTime());
        inNotify.setRemainingDays(request.getRemainingDays());
        inNotifyRepository.saveAndFlush(inNotify);
        return true;
    }

    public boolean outNotify(OutNotifyRequest request){
        OutNotify outNotify = new OutNotify();
        outNotify.setId(UUIDGenerator.getUUID());
        outNotify.setSynId(request.getSynId());
        outNotify.setPlateNumber(request.getPlateNumber());
        outNotify.setParkId(request.getParkId());
        outNotify.setParkName(request.getParkName());
        outNotify.setEntranceTime(request.getEntranceTime());
        outNotify.setUserType(request.getUserType());
        outNotify.setFixParkingId(request.getFixParkingId());
        outNotify.setPushTime(request.getPushTime());
        outNotify.setRemainingDays(request.getRemainingDays());
        outNotifyRepository.saveAndFlush(outNotify);
        return true;
    }



    public void tt(String mobile,String orderId){
        parkProxy.orderPay(mobile,orderId);
    }
    public void simulation1(String plateNum){
        parkProxy.simulation(plateNum);
    }
    public void orderRunPay1(String plateNum,String mobile){
        parkProxy.orderRunPay(plateNum,mobile);
    }
    public void bindCar1(String plateNum,String mobile){
        parkProxy.bindCar(plateNum,mobile);
    }
    public void carnum(String mobile){
        parkProxy.carnum(mobile);
    }
    public void orderPay1(String mobile,String orderId){
        parkProxy.orderPay(mobile,orderId);
    }

    public void couponList() throws UnsupportedEncodingException {
        parkProxy.couponList();
    }

    /**
     * 停车缴费记录
     *
     * @param requestBody
     * @return
     */
    public PageDTO<PayNotifyDTO> parkingRecord(PayNotifyRequest requestBody) {
        //分页
        Integer page = null == requestBody.getPage() ? 0 : requestBody.getPage();
        Integer size = null == requestBody.getSize() ? 10 : requestBody.getSize();
        //优惠券创建时间区间
        String fromDate = requestBody.getFromDate();
        String toDate = requestBody.getToDate();
        //排序状态
        Sort sort = new Sort(Sort.Direction.DESC, "time");
        //搜索关键词
        String keyword = requestBody.getKeyword();
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<PayNotify> paged = payNotifyRepository.findAll((Specification<PayNotify>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtil.isNotEmpty(fromDate)) {
                Date startOfDay = DateUtils.getStartOfDay(DateUtils.strToDate(fromDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("time").as(Date.class), startOfDay));
            }
            if (StringUtil.isNotEmpty(toDate)) {
                Date endOfDay = DateUtils.getEndOfDay(DateUtils.strToDate(toDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("time").as(Date.class), endOfDay));
            }
            if (StringUtil.isNotEmpty(keyword)) {
                    Predicate p = criteriaBuilder.like(root.get("plateNumber").as(String.class), "%" + keyword + "%");
                   /* Predicate p1 =criteriaBuilder.or(criteriaBuilder.like(root.get("couponName").as(String.class), "%" + keyword + "%"),p) ;
                    Predicate p2 =criteriaBuilder.or(criteriaBuilder.like(root.get("senderName").as(String.class), "%" + keyword + "%"),p1) ;
                    */
                   predicates.add(p);
            }
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);
        List<PayNotify> payNotifies = paged.getContent();
        List<PayNotifyDTO> payNotifyDTOS = new LinkedList<>();
        for (PayNotify payNotify : payNotifies) {
            PayNotifyDTO payNotifyDTO = new PayNotifyDTO();
            BeanUtils.copyProperties(payNotify, payNotifyDTO);
            payNotifyDTOS.add(payNotifyDTO);

        }
        PageDTO<PayNotifyDTO> dto = new PageDTO<>();
        dto.setTotal(paged.getTotalElements());
        dto.setList(payNotifyDTOS);
        dto.setPage(page);
        dto.setPageSize(size);
        dto.setKeyword(requestBody.getKeyword());
        dto.setTotalPage(paged.getTotalPages());
        dto.setFromDate(fromDate);
        dto.setToDate(toDate);
        System.out.println(dto);
        return dto;
    }


}
